Skip to content

Conversation

vortex73
Copy link

@vortex73 vortex73 commented Aug 27, 2025

CC: @asl

@vortex73 vortex73 marked this pull request as ready for review August 27, 2025 10:24
@asl
Copy link
Contributor

asl commented Aug 27, 2025

@nikic Will you please review content-wise? Thanks!

@asl
Copy link
Contributor

asl commented Sep 8, 2025

@nikic ping :)

Copy link

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for not reviewing this earlier, I left some comments now.

As a high level note, I think that for the broader audience of a blog post we should probably focus more on the higher level stuff (concepts, design etc) than code snippets. No really specific suggestions on that though.


# Introduction

In this post I'm going to outline details about a new ABI lowering library I've been developing for LLVM as part of GSoC 2025!. The aim was to extract the ABI logic from clang and create a reusable library that any LLVM frontend can use for correct C interoperability.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In this post I'm going to outline details about a new ABI lowering library I've been developing for LLVM as part of GSoC 2025!. The aim was to extract the ABI logic from clang and create a reusable library that any LLVM frontend can use for correct C interoperability.
In this post I'm going to outline details about a new ABI lowering library I've been developing for LLVM as part of GSoC 2025! The aim was to extract the ABI logic from clang and create a reusable library that any LLVM frontend can use for correct C interoperability.


Here's what that looks like in practice:
```cpp
struct Point { double x, y; };
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
struct Point { double x, y; };
struct Point { float x, y; };

I found that using float here makes things even more fun :) This godbolt shows that we end up using 6 different calling conventions on 6 different targets: https://clang.godbolt.org/z/P4fMj7hjY Maybe we can link it somewhere.

Comment on lines +26 to +29
- Does x86-64 pass this in registers or memory?
- What about ARM? PowerPC? WebAssembly?
- Should it be scalarized to `(double, double, double, double)`?
- Or does it need a hidden return parameter?
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- Does x86-64 pass this in registers or memory?
- What about ARM? PowerPC? WebAssembly?
- Should it be scalarized to `(double, double, double, double)`?
- Or does it need a hidden return parameter?
- Are the struct arguments passed in registers or memory?
- If in registers, what register class is used?
- Are multiple values packed into a single register?
- Is the struct returned in registers or using a hidden return parameter?

I'd focus on just the different options here and leave that this is target-dependent to the next sentence.

- Should it be scalarized to `(double, double, double, double)`?
- Or does it need a hidden return parameter?

The answer depends on subtle ABI rules that are target-specific, constantly evolving, and absolutely critical to get right. Miss one detail and you get silent memory corruption that only shows up in release builds.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The answer depends on subtle ABI rules that are target-specific, constantly evolving, and absolutely critical to get right. Miss one detail and you get silent memory corruption that only shows up in release builds.
The answer depends on subtle ABI rules that are target-specific, constantly evolving, and absolutely critical to get right. Miss one detail and you get silent memory corruption.

ABI mismatches typically also show up in non-release builds.

# The Design

<div style="margin:0 auto;">
<img src="/img/abi_flow.png"><br/>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you still have the original around, I'd consider dropping the "register allocator" box. I know what you mean, but it's probably not what people expect when they see the term.

Not really important though, leave it alone if changing the image is a hassle.


# Results

The library and the new typesystem are now successfully integrated into Clang, as part of the PR, and are enabled for BPF and X86-64 Linux targets. Here's what we achieved:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly to above, the wording here isn't super clear on this still being in a PR rather than integrated in upstream Clang.


```
Compare this to the old approach where BPF ABI logic would be scattered across multiple files, mixed with Clang-specific assumptions!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think one bit that's missing here is how these results get back into Clang, i.e. the ABITypeMapper and that we populate the old Clang structs from the new ABI structs so both style are supported at the same time.

<img src="/img/abi_library_benchmarks.png"><br/>
</div>

The results are encouraging. Most compilation stages show essentially no performance difference (well within measurement noise). The 0.20% regression in the final Clang binary size is expected - we've added new code to the codebase. But the actual compilation performance impact is negligible.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 0.20 number is is not a change in Clang binary size, but in time to build Clang (but the rest of what you say of course still applies).


# Future Work

There's still plenty to explore:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also add upstreaming here. Can also link to the PR you opened then.


## Extended Target Support

Currently supporting BPF and X86-64 SysV, but the architecture makes adding ARM, Windows calling conventions, and other targets straightforward.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Currently supporting BPF and X86-64 SysV, but the architecture makes adding ARM, Windows calling conventions, and other targets straightforward.
Currently the ABI library supports the BPF and X86-64 SysV ABIs, but the architecture makes adding ARM, Windows calling conventions, and other targets straightforward.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants